(*    Release 3.00 *)

(*    CoreMain - process startup and exit, args, environment. *)

(*    Copyright (C) 1989 Jensen and Partners. All Rights Reserved*)
(*    Written by Simon Knight.*)

(*    Copyright (C) 1991 Psion PLC. All Rights Reserved*)
(*    Written by NSM.*)

include "corelib.inc"
include "epocdefs.inc"

module CoreMain

(****************************************************************************)
segment _MAGIC(DATA,28H)
segment _INIT(DATA,28H)
segment _CONST(DATA,28H)
segment _DATA(DATA,28H)
segment _BSS(BSS,28H)
segment _BSS_END(BSS,28H)

group DGROUP(_MAGIC,_INIT,_CONST,_DATA,_BSS,_BSS_END)

select _BSS

public  __argbuf :    org 128			(* command line buffer *)
public  __osmajor :   org 2
public  __osminor :   org 2
public __exit_stk :   org 32*CodePtrSize	(* at/onexit function stack *)
public __exit_io :    org CodePtrSize
public __exit_tmp :   org CodePtrSize
public __exit_proc :  org CodePtrSize
public __real_in :    org CodePtrSize
public __real_out :   org CodePtrSize
public __sigsetup :   org 2
public __exitbreak :  org CodePtrSize
public __exitsig :    org CodePtrSize
public @InitCount :   org 2
public @InitEnd :     org 2
public @InitDone :    org 2
public @ExitCode :    org 2
public @StackContextSP : org 2
public @StackContextBP : org 2

select _DATA

extrn __Term2
extrn __init_start
extrn __bss_start

public __exit_ptr :		dw __exit_stk + (32*CodePtrSize)
public __exit_top :		dw __exit_stk + (32*CodePtrSize)
public standard@haltChain :	dw __Term2
public @InitPointer :		dw __init_start
public @InitPriority :		db PRMAX
public  __arg_init :		db 0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn __exit

select _DATA

extrn __exit
extrn __exit_io
extrn __exit_tmp
extrn __exit_proc
extrn __init_start
extrn __const_start
extrn @RecursiveExit
extrn @InitPointer
extrn @InitCount
extrn @InitPriority
extrn @InitEnd
extrn @InitDone
extrn @ExitCode
extrn @StackContextSP
extrn @StackContextBP
extrn $Stage2

select _TEXT

public _exit :

    mov  [@ExitCode], ax
    cmp  byte [@RecursiveExit], 0
    je   notAgain
    call __exit
notAgain:
    not  byte [@RecursiveExit]
    mov  sp, [@StackContextSP]
    mov  bp, [@StackContextBP]
    jmp  near $TerminateProcess

public __InitLoop :

    push di
    push si
    mov  bx, [@InitPointer]
    jmp	 traverseLoop
nextLoop:
    add  bx, InitSize
chainLoop:
traverseLoop:
    cmp  bx, [@InitEnd]
    jae  endOfArray
    mov  al, [@InitPriority]
    cmp  al, [bx][Priority]
    jne  nextLoop
    lea	 ax, [bx][InitSize]
    mov  [@InitPointer], ax
    dec  word [@InitCount]
    call [bx][ProcVar]
    mov  bx, [@InitPointer]
    cmp  word [@InitDone], 0
    je	 traverseLoop
initLoopRet:
    pop  si
    pop  di
    ret  0

endOfArray:
    cmp  word [@InitCount], 0
    je	 stageComplete

endOfList:
    dec  byte [@InitPriority]
    js	 stageComplete
    mov	 bx, __init_start
    jmp  chainLoop

stageComplete:
    inc	 word [@InitDone]
    mov  [@StackContextBP], bp
    mov  [@StackContextSP], sp
    call $Stage2
    mov  [@ExitCode], ax

$TerminateProcess:

public __Term2 :
    extrn __exit_ptr
    extrn __exit_top
    extrn standard@haltChain

(* reset halt chain to allow it to be re-used in termination code *)

    mov  bx, here
    xchg bx, [standard@haltChain]
    call bx

here:
    mov  bp, [@StackContextBP]
    mov  sp, [@StackContextSP]
    mov  si, [__exit_ptr]
    mov  di, [__exit_top]
exitLoop:
    cmp  si, di
    je   loopDone
    call [si]
    add  si, 2
    jmp  exitLoop
loopDone:

    jmp  initLoopRet

public __cleanup :

    mov  cx, [__exit_io]
    jcxz noCall1
    call cx
noCall1:
    mov  cx, [__exit_tmp]
    jcxz noCall2
    call cx
noCall2:
    mov  cx, [__exit_proc]
    jcxz noCall3
    call cx
noCall3:
    ret  0

(******************************************************************************)
section
segment _TEXT(CODE,28H)
segment _BSS(BSS,28H)

__env_buffer : org 256

select _TEXT

public _getenv :

    push di
    push si
    mov	 si, __env_buffer
    mov  di, ax
    mov	 ah, NmGenEnvStringGet
    int	 GenManager
    mov	 ax, si
    jnc  getenvExit
    sub  ax, ax
getenvExit:
    pop  si
    pop  di
    ret  0

(******************************************************************************)
section
segment _TEXT(CODE,28H)

extrn _strlen
extrn _strcpy
extrn _strchr

public _putenv :

    push bx
    push di
    push si
    sub  sp, (256+18)
    cld

    mov  bx, ax
    call _strlen
    mov  di, ax
    test ax, ax
    je   putenvFailed
    cmp  ax, (256+18)
    jae  putenvFailed
    mov  ax, sp
    call _strcpy
    mov  bl, '='
    sub  bh, bh
    call _strchr
    mov	 bx, ax
    mov	 ah, NmGenEnvStringDelete
    test bx, bx
    je	 putenvDelete
    mov  si, bx
    mov  byte [si], 0
    inc	 si
    cmp	 byte [si], 0
    je	 putenvDelete
    mov	 ah, NmGenEnvStringSet
putenvDelete:
    mov  di, sp
    int	 GenManager
    jc   putenvFailed
    sub  ax, ax
putenvExit:
    add  sp, (256+18)
    pop  si
    pop  di
    pop  bx
    ret  0

putenvFailed:
    mov  ax, -1
    jmp  putenvExit

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)

extrn @InitCount
extrn @InitEnd
extrn @InitDone
extrn __init_start
extrn __const_start

select _TEXT

public __InitSetup :

    mov	 ax, __const_start
    sub	 ax, __init_start
    mov	 bl, InitSize
    div  bl
    sub	 ah, ah
    mov	 [@InitCount], ax
    mul	 bl
    add  ax, __init_start
    mov	 [@InitEnd], ax
    and	 word [@InitDone], 0
    ret  0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn __argv
extrn __argc

select _TEXT

extrn _main

public __init2 :

  mov  ax, [__argc]
  mov  bx, __argv
  jmp  near _main

(****************************************************************************)
section
segment _INIT(DATA,28H)
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)
segment _BSS(BSS, 28H)

extrn __setargv
extrn __InitLoop

select _TEXT

do_initargc : (* defined later on ! *)

select _INIT

initargc : dw MAGIC
    	   db PR1
           dw do_initargc

select _BSS

public __argv :   org 32*DataPtrSize
public __argin :  org DataPtrSize
public __argout : org DataPtrSize
public __argapp : org 2

select _DATA

public __argc : dw initargc

select  _TEXT

    call __setargv
    jmp  __InitLoop

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

extrn __exit

select _DATA

extrn __osmajor
extrn __osminor

select _TEXT

public __osversion :

(*
void __osversion(void)
checks Epoc/Os version into __osver
*)

    mov	 ah, NmGenVersion
    int	 GenManager
    push ax
    shr	 ax, 1
    shr	 ax, 1
    shr	 ax, 1
    shr	 ax, 1
    mov  [__osmajor], ah
    mov  [__osminor], al
    pop  ax
    and  ah, 0FH
    mov	 al, 0AH
    mul	 ah
    add  [__osminor], ax
    ret  0

(**************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)

select _DATA

extrn __argv
extrn __argbuf
extrn __argc
extrn __argin
extrn __argout
extrn __argapp
extrn __arg_init
extrn _DatCommandPtr

select _TEXT

extrn _strlen

public __setargv :

  push di
  push si
  cld
  cmp  byte [__arg_init], 0
  jne  initDone
  not  byte [__arg_init]
  mov  word [__argc], 0
  mov  di, [_DatCommandPtr]
  test di, di
  je   initDone
  mov  bx, __argv
  call saveArg
  mov  ax, di
  call _strlen
  add  di, ax
  inc  di
  mov  si, di
  lodsb
  cbw
  add  ax, si
  mov  dx, ax
  mov  di, __argbuf
convLoop:
  cmp  si, dx
  jae  initDone
  lodsb
  test al, al
  je   initDone
  cmp  al, ' '
  je   convLoop
  cmp  al, '<'
  je   gotInRedir
  cmp  al, '>'
  je   gotOutRedir
  cmp  al, '"'
  je   gotString
  dec  si
  mov  al, ' '
gotString:
  mov  cl, al
  call saveArg
locateLoop:
  cmp  si, dx
  jae  gotLocate
  lodsb
  test al, al
  je   gotLocate
  cmp  al, cl
  je   gotLocate
  stosb
  jmp  locateLoop
gotLocate:
  sub  al, al
  stosb
  jmp  convLoop
initDone:
  pop  si
  pop  di
  ret  0
gotInRedir:
  push bx
  mov  bx, __argin
  jmp  goLocate
gotOutRedir:
  cmp  byte [si], '>'
  jne  notAppend
  lodsb
  mov  word [__argapp], ModeAppend
notAppend:
  push bx
  mov  bx, __argout
goLocate:
  cmp  si, dx
  jae  noFileName
  lodsb
  test al, al
  je   noFileName
  cmp  al, ' '
  je   goLocate
  dec  si
  mov  [bx], di
  mov  cl, ' '
  pop  bx
  jmp  locateLoop
noFileName:
  pop  bx
  jmp  initDone

saveArg:
  cmp  word [__argc], 32
  jae  noRoomForMore
  mov  [bx], di
  inc  bx
  inc  bx
  inc  word [__argc]
noRoomForMore:
  ret  0

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

select _DATA

extrn __sigsetup
extrn __exitbreak
extrn __exitsig

select _TEXT

extrn __FloatFinish

public __exit :

(*
void __exit(int code)
terminates process.
*)

    mov  di, ax
    mov  cx, [__exitbreak]
    jcxz noBreak
    call cx
noBreak:
    mov  cx, [__exitsig]
    jcxz noSig
    call cx
noSig:

    call __FloatFinish

    mov	 ah, NmProcId
    int	 ProcManager
    mov	 bx, ax
    mov  ax, di
    mov	 ah, NmProcKill
    int	 ProcManager

(****************************************************************************)
section
segment _DATA(DATA, 28H)
segment _TEXT(CODE,28H)

extrn __exit_proc
extrn __exitbreak
extrn __exitsig
extrn __FloatFinish

public __term_process :

    mov  cx, [__exit_proc]
    jcxz noCall4
    call cx
noCall4:
    mov  cx, [__exitbreak]
    jcxz noBreak
    call cx
noBreak:
    mov  cx, [__exitsig]
    jcxz noSig
    call cx
noSig:
    jmp  near __FloatFinish

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA, 28H)

select _DATA

message : db 0AH,'Floating Point Not Loaded',0AH,0

select _TEXT

extrn _puts

public __real_pdef :
public __real_sdef :

    mov	 ax, message
    jmp	 _puts

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _MAGIC(DATA,28H)
segment _INIT(DATA,28H)
segment _CONST(DATA,28H)
segment _DATA(DATA,28H)
segment _BSS(BSS,28H)
segment _BSS_END(BSS,28H)

group DGROUP(_MAGIC,_INIT,_CONST,_DATA,_BSS,_BSS_END)

extrn __EpocInit
extrn __exit
extrn __cleanup
extrn __osversion
extrn __FloatInit
extrn __InitSetup
extrn __InitLoop
extrn __init2
extrn @ExitCode
select _TEXT			(* Process initialisation starts here *)

public __startup :

  call __EpocInit

  call __FloatInit		(* initialise floating point if present *)
  call __osversion		(* get Epoc/Os version first *)

  call __InitSetup
  call __InitLoop

  call __cleanup

  mov  ax, [@ExitCode]
  jmp  near __exit

public $Stage2 :

  call __init2

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)

extrn __real_in
extrn __real_out
extrn __rreal_in
extrn __rreal_out

select _TEXT

extrn __initsig

public __fp_1 :

    mov  word [__real_in], __rreal_in     (* initialise 'C' fp output *)
    mov  word [__real_out], __rreal_out
    jmp  near __initsig

(****************************************************************************)
section
segment _TEXT(CODE,28H)
segment _DATA(DATA,28H)

extrn __real_in
extrn __real_out
extrn __real_pdef
extrn __real_sdef

select _TEXT

public __fp_0 :

    mov  word [__real_in], __real_sdef
    mov  word [__real_out], __real_pdef
    ret  0

end


